using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.Data;
using System.Globalization;

namespace it.mintlab.mobilenet.mintar
{
    public static class ModelPanelUtils<T> where T : Model, new()
    {
        public static void bindModelToControls(T modelObj, System.Windows.Forms.Control.ControlCollection controls)
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1 && pi.GetValue(modelObj, null) != null)
                {
                    foreach (Control c in controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            //if drop down list
                            if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                if (pi.PropertyType.Equals(typeof(int)))
                                {
                                    ((ComboBox)c).SelectedValue = (int)pi.GetValue(modelObj, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(string)))
                                {
                                    ((ComboBox)c).SelectedItem = (string)pi.GetValue(modelObj, null);
                                }
                                
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((TextBox)c).Text = ((bool)pi.GetValue(modelObj, null)).ToString();
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((TextBox)c).Text = ((DateTime)pi.GetValue(modelObj, null)).ToString(panelAttrs[0].dateFormat);
                                }
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((CheckBox)c).Checked = (bool)pi.GetValue(modelObj, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((DateTimePicker)c).Value = (DateTime)pi.GetValue(modelObj, null);
                                }
                                else
                                {
                                    ((TextBox)c).Text = pi.GetValue(modelObj, null).ToString();
                                }
                            }
                        }
                    }
                }
            }
        }

        public static T getModelFromControls(T modelObj, List<Control> controls)
        {
            //T modelObj = new T();
            //ConstructorInfo ci = TClass.GetConstructor(new Type[] { });
            //T modelObj = (T)ci.Invoke(new object[]{});
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    foreach (Control c in controls)
                    {
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            //if drop down list
                            if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                int value = (int)((ComboBox)c).SelectedValue;
                                if (value == -1)
                                {
                                    MessageBox.Show("Campo '" + panelAttrs[0].label + "' non definito");
                                    return default(T);
                                }
                                else
                                    pi.SetValue(modelObj, value, null);
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    if (c.Text.Equals("True") ||
                                        c.Text.Equals("true") ||
                                        c.Text.Equals("Vero") ||
                                        c.Text.Equals("vero") ||
                                        c.Text.Equals("1"))
                                    {
                                        pi.SetValue(modelObj, true, null);
                                    }
                                    else
                                    {
                                        pi.SetValue(modelObj, false, null);
                                    }
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    try
                                    {
                                        DateTime value = DateTime.ParseExact(c.Text, panelAttrs[0].dateFormat,
                                            CultureInfo.InvariantCulture);

                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non data");
                                        return default(T);
                                    }
                                }
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    pi.SetValue(modelObj, ((CheckBox)c).Checked, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    DateTime date = ((DateTimePicker)c).Value;
                                    date = date.Subtract(new TimeSpan(date.Hour, date.Minute, date.Second));
                                    pi.SetValue(modelObj, date, null);
                                }
                                else if (pi.PropertyType.Equals(typeof(int)))
                                {
                                    try
                                    {
                                        int value = int.Parse(c.Text);
                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non intero");
                                        return default(T);
                                    }
                                }
                                else if (pi.PropertyType.Equals(typeof(decimal)))
                                {
                                    try
                                    {
                                        decimal value = decimal.Parse(c.Text);
                                        pi.SetValue(modelObj, value, null);
                                    }
                                    catch
                                    {
                                        MessageBox.Show("Campo '" + panelAttrs[0].label + "' non decimale");
                                        return default(T);
                                    }
                                }
                                else
                                {
                                    pi.SetValue(modelObj, c.Text, null);
                                }
                            }
                        }
                    }
                }
            }
            return modelObj;
        }

        public static void clearControls(System.Windows.Forms.Control.ControlCollection controls)
        {
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if panel attribute is present
                ModelPanelAttr[] panelAttrs = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                if (panelAttrs.Length >= 1)
                {

                    foreach (Control c in controls)
                    {
                        bool isModelControl = false;
                        if (c.Name.Equals("bx" + pi.Name))
                        {
                            isModelControl = true;
                            //if rating type
                            if (panelAttrs[0].rating)
                            {
                                ((StarsPanel)c).resetRate();
                            }
                            //if drop down list
                            else if (!panelAttrs[0].listingTable.Equals(""))
                            {
                                ((ComboBox)c).SelectedIndex = 0;
                            }
                            // if text box forcing for properties
                            else if (panelAttrs[0].forceTextBox)
                            {
                                ((TextBox)c).Text = "";
                            }
                            else
                            {
                                if (pi.PropertyType.Equals(typeof(bool)))
                                {
                                    ((CheckBox)c).CheckState = CheckState.Indeterminate;
                                }
                                else if (pi.PropertyType.Equals(typeof(DateTime)))
                                {
                                    ((DateTimePicker)c).Value = DateTime.Now;
                                }
                                else
                                {
                                    ((TextBox)c).Text = "";
                                }
                            }
                        }
                        if (!isModelControl) { 
                            if(c is TextBox)
                                ((TextBox)c).Text = "";
                        }
                    }
                }
            }
        }

        public static T validateModelFromControls(System.Windows.Forms.Control.ControlCollection controls)
        {
            T modelObj = new T();
            //Model modelObj = Model.createModel(typeof(T));
            Type TClass = typeof(T);
            PropertyInfo[] properties = TClass.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                //if any attribute is present
                ModelPanelAttr[] attrsPan = (ModelPanelAttr[])pi.GetCustomAttributes(typeof(ModelPanelAttr), true);
                ModelAttr[] attrs = (ModelAttr[])pi.GetCustomAttributes(typeof(ModelAttr), true);

                if (attrsPan.Length >= 1)
                {
                    bool required = attrsPan[0].required;
                    if (attrs[0].insertable)
                    {
                        foreach (Control c in controls)
                        {
                            if (c.Name.Equals("bx" + pi.Name))
                            {
                                //if rating type
                                if (attrsPan[0].rating)
                                {
                                    int rate = ((StarsPanel)c).getRate();
                                    if (rate == 0 && required)
                                    {
                                        MessageBox.Show("Campo '" + attrsPan[0].label + "' ha rate nullo");
                                        return default(T);
                                    }
                                    else
                                        pi.SetValue(modelObj, rate, null);
                                }
                                //if drop down list
                                else if (!attrsPan[0].listingTable.Equals(""))
                                {
                                    if (pi.PropertyType.Equals(typeof(int)))
                                    {
                                        int value = (int)((ComboBox)c).SelectedValue;
                                        if (value == -1 && required)
                                        {
                                            MessageBox.Show("Campo '" + attrsPan[0].label + "' non definito");
                                            return default(T);
                                        }
                                        else
                                            pi.SetValue(modelObj, value, null);
                                    }
                                    else if (pi.PropertyType.Equals(typeof(string)))
                                    {
                                        string value = (string)((ComboBox)c).SelectedItem;
                                        if (required && (value == null || value.Equals("")))
                                        {
                                            MessageBox.Show("Campo '" + attrsPan[0].label + "' non definito");
                                            return default(T);
                                        }
                                        else
                                            pi.SetValue(modelObj, value, null);
                                    }
                                    
                                }
                                else
                                {
                                    if (pi.PropertyType.Equals(typeof(bool)))
                                    {
                                        pi.SetValue(modelObj, ((CheckBox)c).Checked, null);
                                    }
                                    else if (pi.PropertyType.Equals(typeof(DateTime)))
                                    {
                                        pi.SetValue(modelObj, ((DateTimePicker)c).Value, null);
                                    }
                                    else if (pi.PropertyType.Equals(typeof(int)))
                                    {
                                        try
                                        {
                                            int value = int.Parse(c.Text);
                                            pi.SetValue(modelObj, value, null);
                                        }
                                        catch
                                        {
                                            if (required || !c.Text.Equals(""))
                                            {
                                                MessageBox.Show("Campo '" + attrsPan[0].label + "' non numerico");
                                                return default(T);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (required && c.Text.Equals(""))
                                        {
                                            MessageBox.Show("Campo '" + attrsPan[0].label + "' non definito");
                                            return default(T);
                                        }
                                        pi.SetValue(modelObj, c.Text, null);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return modelObj;
        }

    }
}
